﻿// DataTable Extensions from Finaquant Analytics
// Provided with the GNU General Public License (GPL)
// For license information see http://www.gnu.org/licenses/licenses.html
//
// Copyright ©  - Finaquant Analytics GmbH - http://finaquant.com/
// 
// NOTE: Non-commercial and free .net library Finaquant Protos
// which is required for these DataTable Extensions
// can be downloaded at http://finaquant.com/FinaquantProtos

using FinaquantProtos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.OleDb;
using System.Text.RegularExpressions;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;

namespace FinaquantDataTableExtensions
{
    class Demo
    {
        /// <summary>
        /// Demo function for open-source DataTable extensions
        /// Finaquant Analytics - http://finaquant.com/
        /// </summary>
        public static void DataTable_Extensions_DEMO()
        {
            #region "Create a test table of type MatrixTable"

            // define metadata
            MetaData md = MetaData.CreateEmptyMetaData();
            MetaData.AddNewField(md, "country", FieldType.TextAttribute);
            MetaData.AddNewField(md, "product", FieldType.TextAttribute);
            MetaData.AddNewField(md, "model", FieldType.IntegerAttribute);
            MetaData.AddNewField(md, "date", FieldType.DateAttribute);
            MetaData.AddNewField(md, "sales", FieldType.KeyFigure);

            // define table structure
            var SalesTableFields = TableFields.CreateEmptyTableFields(md);
            TableFields.AddNewField(SalesTableFields, "country");
            TableFields.AddNewField(SalesTableFields, "product");
            TableFields.AddNewField(SalesTableFields, "model");
            TableFields.AddNewField(SalesTableFields, "date");
            TableFields.AddNewField(SalesTableFields, "sales");

            // create test table by combinating field values
            // ... random values for key figures

            // value set for text attributes
            TextVector CountryVal = TextVector.CreateVectorWithElements("Peru", "Paraguay", "Argentina");
            TextVector ProductVal = TextVector.CreateVectorWithElements("Car", "Bus", "Bicycle");
            // value set for numeric attribûtes
            NumVector ModelVal = NumVector.CreateVectorWithElements(2008, 2009, 2010);
            NumVector DateVal = NumVector.CreateSequenceVector(
                StartValue: DateFunctions.DayToNumber(1, 3, 2010),
                Interval: 10, nLength: 5);

            // initiate field value dictionaries
            var TextAttribValues = new Dictionary<string, TextVector>();
            var NumAttribValues = new Dictionary<string, NumVector>();
            // assign a value vector to each field
            TextAttribValues["country"] = CountryVal;
            TextAttribValues["product"] = ProductVal;
            NumAttribValues["model"] = ModelVal;
            NumAttribValues["date"] = DateVal;

            // default range for all key figures
            KeyValueRange DefaultRangeForAllKeyFigures = KeyValueRange.CreateRange(2000, 20000);

            // create test table by combinating all possible attribute values
            var SalesTable = MatrixTable.CombinateFieldValues_B(SalesTableFields,
                TextAttribValues, NumAttribValues, DefaultRangeForAllKeyFigures);

            // unrounded numbers look ugly!
            // round all key figures to 2 digits after decimal point
            SalesTable = MatrixTable.TransformKeyFigures(SalesTable, x => Math.Round(x, 2),
                InputKeyFig: null, OutputKeyFig: null);

            #endregion "Create a test table of type MatrixTable"

            DataTable dt = new DataTable();

            // convert MatrixTable to DataTable
            DataTable SalesTbl = dt.ImportFromMatrixTable(SalesTable);

            // view SalesTbl - multi-thread:
            // table viewer can remain open in a separate thread as the main program runs
            TableViewer tw1 = SalesTbl.ViewTable_MultiThread("Sales table, multi-thread");

            // wait a bit
            System.Threading.Thread.Sleep(200);

            // get element values
            Console.WriteLine("Table element (country, row = 3): {0}",
                SalesTbl.GetElementValue("country", 2));

            Console.WriteLine("Table element (column = 4, row = 3): {0}",
                SalesTbl.GetElementValue(3, 2));

            MessageBox.Show("Press OK to continue.");

            // set element value
            SalesTbl.SetElementValue("country", 3, "Venezuela");

            // view table - single-thread
            TableViewer tw2 = SalesTbl.ViewTable_SingleThread("Sales table with Venezuela at 4. row, single-thread");

            // wait a bit
            System.Threading.Thread.Sleep(200);
            MessageBox.Show("See Venezuela as the country at 4. row of table. Press OK to continue.");

            // print DataTable to console; convert DataTable to string
            Console.WriteLine("SalesTbl: \n {0}", SalesTbl.ConvertToString());

            // partition DataTable
            NumVector RowIndices = NumVector.CreateVectorWithElements(0, 2, 4, 6);
            TextVector Columns = TextVector.CreateVectorWithElements("country", "date");

            DataTable SubSalesTbl = SalesTbl.Partition(Columns, RowIndices);

            // view table
            var tw3 = SubSalesTbl.ViewTable_MultiThread("Subtable of sales table, multi-thread");

            // convert DataTable to MatrixTable
            MatrixTable mTbl = SalesTbl.ConvertToMatrixTable(md);
            MatrixTable.View_MatrixTable(mTbl, "sales table as MatrixTable");

            // re-locate a multi-thread table viewer
            System.Threading.Thread.Sleep(500);
            MessageBox.Show("Press OK to relocate subtable - unless you already closed it manually.");
            if (tw3.Visible) tw3.Invoke(new LocationDelegate(tw3.SetDesktopLocation), (int)-20, (int)-20);

            // close a multi-thread table viewer
            System.Threading.Thread.Sleep(500);
            MessageBox.Show("Press OK to close subtable - unless you already closed it manually.");
            if (tw3.Visible) tw3.Invoke(new CloseDelegate(tw3.Close));

            // export sales table to an XML file (save DataTable as XML file)
            string filename = "SalesTable";
            string directory = @"C:\Windows\Temp\";     // check if this is a valid directory on your computer!
            SalesTbl.ExportTableToXMLfile(filename, directory, IfAddTimeStamp: false);

            // import table from XML file (read DataTable from XML file)
            System.Threading.Thread.Sleep(200);
            var SalesTblFromXML = dt.ImportTableFromXMLfile(filename, directory);
            var tw4 = SalesTblFromXML.ViewTable_MultiThread("Sales table imported from XML file");
        }

        // delegate type required for TableViewer_FormsAndThreads()
        private delegate void CloseDelegate();

        // delegate type required for TableViewer_FormsAndThreads()
        private delegate void LocationDelegate(int x, int y);
    }
}

